﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SMA.GENTEv1.Dados;
using System.Linq.Expressions;

namespace SMA.GENTEv1
{
    public class GrupoEmail
    {

        #region Variaveis Membro
        private int _idGrupoEmail;
        private string _descricao;
        private Status _status;
        private Organizacao _organizacao;
        private List<PessoaEmail> _pessoaEmail;
        private bool _selecionado;
        private GENTEEntities _context;
        #endregion

        #region Propriedades
        public int IdGrupoEmail
        {
            get { return _idGrupoEmail; }
            set { _idGrupoEmail = value; }
        }
        public string Descricao
        {
            get { return _descricao; }
            set { _descricao = value; }
        }
        public Status Status
        {
            get { return _status; }
            set { _status = value; }
        }
        public Organizacao Organizacao
        {
            get { return _organizacao; }
            set { _organizacao = value; }
        }
        public bool Selecionado
        {
            get { return _selecionado; }
            set { _selecionado = value; }
        }
        public List<PessoaEmail> PessoaEmail
        {
            get { return _pessoaEmail; }
            set { _pessoaEmail = value; }
        }
        #endregion

        #region Contrutores
        public GrupoEmail()
        {
            try
            {
                _context = new GENTEEntities();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public GrupoEmail(int idGrupoEmail)
        {
            try
            {
                _context = new GENTEEntities();
                Carregar(idGrupoEmail, false);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public GrupoEmail(int idGrupoEmail, bool isCarregaPessoas)
        {
            try
            {
                _context = new GENTEEntities();
                Carregar(idGrupoEmail, isCarregaPessoas);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region Metodos Privados
        private void Carregar(int idGrupoEmail, bool isCarregaPessoas)
        {
            try
            {
                var consulta = from ge in _context.tab_grupo_email
                               where ge.Id_grupo_email == idGrupoEmail
                               select new
                               {
                                   ge.Id_grupo_email,
                                   ge.descricao,
                                   ge.tab_status.id_status,
                                   ge.tab_organizacao.Id_organizacao
                               };
                
                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    this._idGrupoEmail = list.Id_grupo_email;
                    this._descricao = list.descricao;
                    this._status = new Status(list.id_status);
                    //this._idOrganizacao = list.Id_organizacao;
                    this._organizacao = new Organizacao(list.Id_organizacao);

                    if (isCarregaPessoas)
                        CarregaPessoasEmail();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        private void CarregaPessoasEmail()
        {
            try
            {
                PessoaEmail pessoaEmail = new PessoaEmail();
                this._pessoaEmail = pessoaEmail.SelectPorGrupo(this._idGrupoEmail);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        private static Expression<Func<TElement, bool>> BuildContainsExpression<TElement, TValue>(Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values)
        {
            if (null == valueSelector)
            {
                throw new
                    ArgumentNullException("valueSelector");
            }
            if (null == values) { throw new ArgumentNullException("values"); }

            ParameterExpression p = valueSelector.Parameters.Single();
            if (!values.Any())
            {
                return e => false;
            }

            var equals = values.Select(value =>
            (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value,
            typeof(TValue))));
            var body = equals.Aggregate<Expression>((accumulate, equal) =>
            Expression.Or(accumulate, equal));
            return Expression.Lambda<Func<TElement, bool>>(body, p);
        }
        private int RetornaId(string descricao, int idOrganizacao)
        {
            try
            {
                int idGrupoEmail = 0;

                var consulta = from ge in _context.tab_grupo_email
                               where ge.descricao == descricao
                               && ge.tab_organizacao.Id_organizacao == idOrganizacao
                               orderby ge.Id_grupo_email descending
                               select new
                               {
                                   ge.Id_grupo_email,
                                   ge.descricao,
                                   ge.tab_status.id_status,
                                   ge.tab_organizacao.Id_organizacao
                               };

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    idGrupoEmail = list.Id_grupo_email;
                }

                return idGrupoEmail;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        private int RetornaIdEmailGrupo(int idEmailPessoa, int idGrupoEmail)
        {
            try
            {
                int idGrupoPessoa = 0;

                var consulta = from gep in _context.tab_email_grupo_email
                               where gep.tab_pessoa_email.Id_email == idEmailPessoa
                               && gep.tab_grupo_email.Id_grupo_email == idGrupoEmail
                               select gep;

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    idGrupoPessoa = list.Id_grupo_email_pessoal;
                }

                return idGrupoPessoa;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region Metodos Publicos

        #region Metodos de Selecao
        public List<GrupoEmail> SelectAll()
        {
            try
            {
                List<GrupoEmail> listGrupoEmail = new List<GrupoEmail>();

                var consulta = from ge in _context.tab_grupo_email
                               select new
                               {
                                   ge.Id_grupo_email,
                                   ge.descricao,
                                   ge.tab_status.id_status,
                                   ge.tab_organizacao.Id_organizacao
                               };

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    GrupoEmail grupoEmail = new GrupoEmail();
                    grupoEmail.IdGrupoEmail = list.Id_grupo_email;
                    grupoEmail.Descricao = list.descricao;
                    grupoEmail.Status = new Status(list.id_status);
                    //grupoEmail.IdOrganizacao = list.Id_organizacao;
                    grupoEmail.Organizacao = new Organizacao(list.Id_organizacao);

                    listGrupoEmail.Add(grupoEmail);
                }

                return listGrupoEmail;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public List<GrupoEmail> SelectPor(string descricao)
        {
            try
            {
                List<GrupoEmail> listGrupoEmail = new List<GrupoEmail>();

                var consulta = from ge in _context.tab_grupo_email
                               where ((descricao != "") ? ge.descricao.StartsWith(descricao) : 1 == 1)
                               select new
                               {
                                   ge.Id_grupo_email,
                                   ge.descricao,
                                   ge.tab_status.id_status,
                                   ge.tab_organizacao.Id_organizacao
                               };

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    GrupoEmail grupoEmail = new GrupoEmail();
                    grupoEmail.IdGrupoEmail = list.Id_grupo_email;
                    grupoEmail.Descricao = list.descricao;
                    grupoEmail.Status = new Status(list.id_status);
                    //grupoEmail.IdOrganizacao = list.Id_organizacao;
                    grupoEmail.Organizacao = new Organizacao(list.Id_organizacao);

                    listGrupoEmail.Add(grupoEmail);
                }

                return listGrupoEmail;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public List<GrupoEmail> SelectPorWfParametro(int idWfParametro)
        {
            try
            {
                List<GrupoEmail> listGrupoEmail = new List<GrupoEmail>();

                var consulta = from ge in _context.tab_grupo_email
                               join wfge in _context.tab_configuracao_parametro_workflow_grupo_email on ge.Id_grupo_email equals wfge.tab_grupo_email.Id_grupo_email
                               join wf in _context.tab_configuracao_parametro_workflow on wfge.tab_configuracao_parametro_workflow.id_parametro_workflow equals wf.id_parametro_workflow
                               where wf.id_parametro_workflow == idWfParametro
                               select new
                               {
                                   ge.Id_grupo_email,
                                   ge.descricao,
                                   ge.tab_status.id_status,
                                   ge.tab_organizacao.Id_organizacao
                               };

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    GrupoEmail grupoEmail = new GrupoEmail();
                    grupoEmail.IdGrupoEmail = list.Id_grupo_email;
                    grupoEmail.Descricao = list.descricao;
                    grupoEmail.Status = new Status(list.id_status);
                    //grupoEmail.IdOrganizacao = list.Id_organizacao;
                    grupoEmail.Organizacao = new Organizacao(list.Id_organizacao);

                    listGrupoEmail.Add(grupoEmail);
                }

                return listGrupoEmail;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public List<GrupoEmail> SelectPor(string descricao, List<Status> listStatus, int idTipoOrgan)
        {
            try
            {
                List<GrupoEmail> listGrupoEmail = new List<GrupoEmail>();

                bool pesquisaStatus = false;
                Status status = new Status();
                int[] codStatus = status.ObterCodigosStatus(listStatus);

                foreach (Status item in listStatus)
                {
                    pesquisaStatus = true;
                    break;
                }

                var consulta = (from ge in (pesquisaStatus) ? _context.tab_grupo_email.Where((BuildContainsExpression<tab_grupo_email, int>(item => item.tab_status.id_status, codStatus))) : _context.tab_grupo_email
                               join org in _context.tab_organizacao on ge.tab_organizacao.Id_organizacao equals org.Id_organizacao
                               join tporgan in _context.tab_tporgan_organ on org.Id_organizacao equals tporgan.tab_organizacao.Id_organizacao
                               where ((descricao != "") ? ge.descricao.StartsWith(descricao) : 1 == 1)
                               && ((idTipoOrgan != 0) ? tporgan.tab_tipo_organizacao.id_tipo_organizacao == idTipoOrgan : 1 == 1)
                               select new
                               {
                                   ge.Id_grupo_email,
                                   ge.descricao,
                                   ge.tab_status.id_status,
                                   ge.tab_organizacao.Id_organizacao
                               }).Distinct();

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    GrupoEmail grupoEmail = new GrupoEmail();
                    grupoEmail.Organizacao = new Organizacao(list.Id_organizacao);
                    grupoEmail.IdGrupoEmail = list.Id_grupo_email;
                    grupoEmail.Descricao = grupoEmail.Organizacao.NomeFantasia + " - " + list.descricao;
                    grupoEmail.Status = new Status(list.id_status);

                    listGrupoEmail.Add(grupoEmail);
                }

                return listGrupoEmail;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public List<GrupoEmail> SelectPorTipoOrgan(int idTipoOrgan)
        {
            try
            {
                List<GrupoEmail> listGrupoEmail = new List<GrupoEmail>();

                var consulta = from ge in _context.tab_grupo_email
                               join org in _context.tab_organizacao on ge.tab_organizacao.Id_organizacao equals org.Id_organizacao
                               join tporgan in _context.tab_tporgan_organ on org.Id_organizacao equals tporgan.tab_organizacao.Id_organizacao
                               where tporgan.tab_tipo_organizacao.id_tipo_organizacao == idTipoOrgan
                               select new
                               {
                                   ge.Id_grupo_email,
                                   ge.descricao,
                                   ge.tab_status.id_status,
                                   ge.tab_organizacao.Id_organizacao
                               };

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    GrupoEmail grupoEmail = new GrupoEmail();
                    grupoEmail.IdGrupoEmail = list.Id_grupo_email;
                    grupoEmail.Descricao = list.descricao;
                    grupoEmail.Status = new Status(list.id_status);
                    //grupoEmail.IdOrganizacao = list.Id_organizacao;
                    grupoEmail.Organizacao = new Organizacao(list.Id_organizacao);

                    listGrupoEmail.Add(grupoEmail);
                }

                return listGrupoEmail;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public List<GrupoEmail> SelectPorOrgan(int idOrganizacao)
        {
            try
            {
                List<GrupoEmail> listGrupoEmail = new List<GrupoEmail>();

                var consulta = from ge in _context.tab_grupo_email
                               join org in _context.tab_organizacao on ge.tab_organizacao.Id_organizacao equals org.Id_organizacao
                               where org.Id_organizacao == idOrganizacao
                               select new
                               {
                                   ge.Id_grupo_email,
                                   ge.descricao,
                                   ge.tab_status.id_status,
                                   ge.tab_organizacao.Id_organizacao
                               };

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    GrupoEmail grupoEmail = new GrupoEmail();
                    grupoEmail.IdGrupoEmail = list.Id_grupo_email;
                    grupoEmail.Descricao = list.descricao;
                    grupoEmail.Status = new Status(list.id_status);
                    //grupoEmail.IdOrganizacao = list.Id_organizacao;
                    grupoEmail.Organizacao = new Organizacao(list.Id_organizacao);

                    listGrupoEmail.Add(grupoEmail);
                }

                return listGrupoEmail;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public List<GrupoEmail> SelectPorOrgan(int idOrganizacao, int idWfConfigParametro)
        {
            try
            {
                List<GrupoEmail> listGrupoEmail = new List<GrupoEmail>();
                List<GrupoEmail> listTemp = SelectPorWfParametro(idWfConfigParametro);

                var consulta = from ge in _context.tab_grupo_email
                               join org in _context.tab_organizacao on ge.tab_organizacao.Id_organizacao equals org.Id_organizacao
                               where org.Id_organizacao == idOrganizacao
                               select new
                               {
                                   ge.Id_grupo_email,
                                   ge.descricao,
                                   ge.tab_status.id_status,
                                   ge.tab_organizacao.Id_organizacao
                               };

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    GrupoEmail grupoEmail = new GrupoEmail();
                    grupoEmail.IdGrupoEmail = list.Id_grupo_email;
                    grupoEmail.Descricao = list.descricao;
                    grupoEmail.Status = new Status(list.id_status);
                    //grupoEmail.IdOrganizacao = list.Id_organizacao;
                    grupoEmail.Organizacao = new Organizacao(list.Id_organizacao);

                    foreach (GrupoEmail grupoTemp in listTemp)
                    {
                        if (grupoTemp.IdGrupoEmail == list.Id_grupo_email)
                        {
                            grupoEmail.Selecionado = true;
                            break;
                        }
                    }

                    listGrupoEmail.Add(grupoEmail);
                }

                return listGrupoEmail;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region Metodos de Persistencia
        public void Salvar()
        {
            try
            {
                if (_idGrupoEmail == 0)
                {
                    tab_grupo_email tabGrupoEmail = new tab_grupo_email();
                    tabGrupoEmail.descricao = _descricao;
                    tabGrupoEmail.tab_statusReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_status", "id_status", _status.IdStatus);
                    tabGrupoEmail.tab_organizacaoReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_organizacao", "Id_organizacao", _organizacao.IdOrganizacao);

                    _context.AddTotab_grupo_email(tabGrupoEmail);
                    _context.SaveChanges();

                    _idGrupoEmail = RetornaId(_descricao, _organizacao.IdOrganizacao);

                    //Salvando GrupoEmailPessoa
                    SalvarEmail();
                    
                }
                else
                {
                    tab_grupo_email tabGrupoEmail = (from ge in _context.tab_grupo_email
                                                     where ge.Id_grupo_email == _idGrupoEmail
                                                     select ge).First();

                    tabGrupoEmail.descricao = _descricao;
                    tabGrupoEmail.tab_statusReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_status", "id_status", _status.IdStatus);
                    //tabGrupoEmail.tab_organizacaoReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_organizacao", "Id_organizacao", _organizacao.IdOrganizacao);

                    _context.SaveChanges();

                    //Salvando GrupoEmailPessoa
                    SalvarEmail();

                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public void SalvarEmail()
        {
            try
            {
                if (_idGrupoEmail != 0)
                {   
                    foreach (PessoaEmail item in _pessoaEmail)
                    {
                        int idGrupoEmailPessoa = RetornaIdEmailGrupo(item.IdPessoaEmail, _idGrupoEmail);

                        if (idGrupoEmailPessoa == 0)
                        {
                            tab_email_grupo_email tabEmailGrupo = new tab_email_grupo_email();
                            tabEmailGrupo.tab_grupo_emailReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_grupo_email", "Id_grupo_email", _idGrupoEmail);
                            tabEmailGrupo.tab_pessoa_emailReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_pessoa_email", "Id_email", item.IdPessoaEmail);

                            _context.AddTotab_email_grupo_email(tabEmailGrupo);
                            _context.SaveChanges();
                        }
                        else
                        {
                            tab_email_grupo_email tabEmailGrupo = (from gep in _context.tab_email_grupo_email
                                                                   where gep.Id_grupo_email_pessoal == idGrupoEmailPessoa
                                                                   select gep).First();

                            tabEmailGrupo.tab_grupo_emailReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_grupo_email", "Id_grupo_email", _idGrupoEmail);
                            tabEmailGrupo.tab_pessoa_emailReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_pessoa_email", "Id_email", item.IdPessoaEmail);

                            _context.SaveChanges();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #endregion

    }
}
